<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象 类 面向对象</title>
</head>
<body>
    <pre>
        对象被定义被一组无序的属性集合。散列表？
        对象的属性分数据属性 和 访问器属性
        数据属性 包含一个保存数据值的位置。值会从这个位置读取，也会被写入到这个位置。
        它有4个特性
        [Configurable]  可配置其特性 也就是能否再次调用defineProperty去修改其特性 如果为false则 对其进行任何 非writable的操作都会报错 也不能delete
        [Enumerable] 可遍历 即可读
        [Writable] 是否可修改
        [Value] 值 默认 undefined

        访问器属性 不包含值 但是有getter 和 setter 
        [Configurable]
        [Enumerable] 
        [getter] 读取时调用
        [setter] 修改时调用
         所以直接设值的都是数据属性,设置get set都是访问器属性,并且 configurable enumerable 都是true
        
        构造函数的原型对象   就是实例的原型
        Object.prototype.__proto__ === null 
        Object.assign(target , source) 
        结果是目标的setter 和 来源的 getter;不会递归，只会第一层合并
    </pre>
    <script type="text/javascript">
        let a = new Object() 
        let b = {}

        
        console.log(a.__prototype === Object.prototype) 
        // true
        //调用此方法时 enumerable configurable writable 默认false；
        Object.defineProperty(b, 'key1', {
            value: 0,
            enumerable: true ,
            configurable:false,
            writable: true 
        })
/* 只定义 get 或set 会导致这个访问器属性 不可修改 或者 不可读取 遍历for-in （结果是undefined ）
b.hasOwnProperty('name')
true*/
        Object.defineProperty(b, 'name', {
            set(val) { 
                if(val ==='111'){
                    this.name = val
                }
            },
        })
            console.log(Object.getOwnPropertyDescriptor(b, 'key1'))
        Object.defineProperty(b, 'key1', {
            writable: false
        })
        console.log(Object.getOwnPropertyDescriptor(b, 'key1'))

(obj,{[key]: {options}})
/* Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
    at Function.defineProperties (<anonymous>)
        不能同时设置 访问器属性 数据属性*/
        Object.defineProperties(b, {
            key2:{
                configurable: true ,
                enumerable:true ,
                get(){
                    return 4
                },
                set(val) {
                    this.key2 = Number(val)
                }

            },
            key3: {
                writable:false ,
                configurable: false ,

            }
        })

/* 那么能否改变呢 改变之后 访问器属性还在不在,
不在了 访问器的get set 特性都没了  enumerable 和configuarable 还是原来的*/
Object.defineProperty(b, 'key2', {
    writable:false 
})

let des =  Object.getOwnPropertyDescriptor(b,'key2')
console.log(des)
        /*{
        configurable: true
        enumerable: false
        value: undefined
        writable: false}
        访问器属性会包括 get  set 类型是 function
        */
// 对应的有 多属性 特性
const features = Object.getOwnPropertyDescriptors(b)

const book = {
    get page(){
        return 10
    },
    set page(val){
        this.page = Number(val)
    },
    set log(val){
        return '快去看书'
    },
    name: '百炼刚',
    author:'unknown'
}

const bookfeature = Object.getOwnPropertyDescriptors(book)
console.log(features, bookfeature)
/*
{
    "key1": {
        "value": 0,
        "writable": true,
        "enumerable": true,
        "configurable": true
    },
    "name": {
        "enumerable": false,
        "configurable": false
    },
    "key2": {
        "writable": false,
        "enumerable": true,
        "configurable": true
    },
    "key3": {
        "writable": false,
        "enumerable": false,
        "configurable": false
    }
}
*/
// 效果和 === 差不多  差别在 -0 0  +0  NaN
console.log(Object.is(0,-0)) // false
console.log(Object.is(0,+0)) // true
console.log(Object.is(+0,-0)) // false
console.log(Object.is(NaN,NaN)) // true
/*现在  */

    function factory(){

        return {
            name :'无名',
            walk (){
                console.log('%c奔跑吧', 'color:#23aded')
            }
        }
    }
    let p1 = factory() ;p1.walk()

    function Person(name ) {
        this.name = name ;
        this.walk = function () {
            console.log('%c奔跑吧', 'color:#23aded')
            
        }
    }

    function Person2(name ) {
        this.name = name ;
        Person2.prototype.walk = function () {
            console.log('%c奔跑吧', 'color:#23aded')
            
        }
    }

    function SuperType(){

    }
    function SubType() {
        SubType.prototype = new SubType() ;

    }

    class People {
        constructor(name, sex){
            this.name = name ;
            this.sex = sex ;
        }

        name = '' ;
        sex = 'male';

        say(word){
            alert(word);
        }

    }

    class Student extends People {
        constructor(name, sex){
            /*super 只能在子类中调用 ， 在子类中必须在调用super后才能使用this, 如果子类没有constructor 子类会自动调用super 且传参 到父类*/
            super(name, sex)
        }

        eduNumber = 000;
        class = '' ;
        grade = '' ;
        score = 000
    }


    new Proxy({}, {
        get(target, key){
            return Reflect.get(target, key)
        },
        set(target,key , val){
            //some code 严格模式 这里要返回一个逻辑值
            return Reflect.set(target, key, val)
        }
    })

    function reactive(obj){
        return  new Proxy(obj, { get(target, key){

        },
        set(target, key, val){
            
        }}
        )
    }
    </script>
</body>
</html>